home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / hardware / gm1507 / g_mouse.pas < prev    next >
Pascal/Delphi Source File  |  1994-10-27  |  25KB  |  1,041 lines

  1. { --------------------------------------------------------------------------- }
  2. { G_MOUSE.PAS  g_Mouse Interface Unit - graphical mouse pointer in text mode  }
  3. {             80x25. Borland Pascal 7 version. Supports both real and protec- }
  4. {             ted modes.                                                      }
  5. {                                          }
  6. {                                   Version 1.50.7 }
  7. {                              Written by Bobby Z. }
  8. {                       Copyright(c) 1993,94 by B-coolWare }
  9. { --------------------------------------------------------------------------- }
  10.                                       "Nice, nice. Not excellent, but nice..."
  11.  
  12.                                 (Mel Brooks)
  13.  
  14.   License.
  15.   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  16.  
  17.  SOFTWARE STATUS:
  18.  
  19.  This software is copyrighted free one. This means that it is distributed
  20.   free of charge and that you must keep copyright notice with it. Usually this
  21.   also means that you cannot modify the code, but it is not the case with
  22.   this one (see grant of license for details). Note that it is not public
  23.   domain software, that is author reserves copyright for it as well as some
  24.   other rights.
  25.  
  26.  GRANT OF LICENSE:
  27.  
  28.  You are hereby granted the right to use this software in either commercial
  29.   or non-commercial products provided that you do not charge any extra fee
  30.   for this code and that you keep copyright notice unchanged. 
  31.  You are also granted the right to distribute this code freely in its original
  32.   unmodified form provided that you do not charge any fee that exceed your
  33.   expences from distributing it (for example, uploading to commercial network).
  34.  You also may modify the code to add new features or eliminate bugs or
  35.   incompatibilites you discovered and distribute modified code provided that
  36.   you add a notice that the code was modified. If you do any modifications
  37.   to the code, please send me modified version so that I'll be able to
  38.   reflect changes in the next releases. Regardless of the extent of modifica-
  39.   tions the code should remain free and will still copyright(c) by B-coolWare. 
  40.  If you break any of the rules mentioned you'll be liable for violation of
  41.   Russian Copyright Law in Computer Programs and Databases as well as other
  42.   national or international laws and treaties. The parties that acquired this
  43.   code from you will still have their rights as long as they comply with this
  44.   license.
  45.  
  46.  DISCLAIMER:
  47.  
  48.  Author disclaims all warranties, whether express or implied, of code quality,
  49.   reliability or fitness for a particular purpose. I can only guarantee that it
  50.   will occupy disk space. Though this code was thoroughly tested, the possibi-
  51.   lity of errors can't be eliminated. Do not blame me if something goes wrong -
  52.   you were warned.
  53.  
  54.  AUTHOR'S LIABILITY:
  55.  
  56.  In case of taking damage due to use, misuse or inability to use, this code,
  57.   whether it is physical damage to your hardware, loss of data or profits,
  58.   or any similar damages author shall not be liable for it. The whole risk is
  59.   with you.
  60.  
  61.  AUTHOR'S EXCLUSIVE RIGHTS:
  62.  
  63.  Author reserves the right to use this code in any commercial or non-
  64.   commercial software of his own design, the right to change the code partially
  65.   or in whole without notification to its users and the right to change its
  66.   status (to shareware, for example).
  67.  
  68.  How to contact author:
  69.  ~~~~~~~~~~~~~~~~~~~~~~
  70.  If you experiencing problems with this code or have any suggestions, bug
  71.   fixes or just wanna chat, refer to the following addresses:
  72.  
  73.   e-mail (preferrable):
  74.  
  75.   2:5028/52.6 (FIDOnet)
  76.   bob@ymz.yaroslavl.su (internet)
  77.  
  78.   paper mail:
  79.  
  80.   150031,
  81.   10/4/13 Dobrynina Str.,
  82.   Yaroslavl, 
  83.   Russia
  84.  
  85.   Vladimir M. Zakharychev (aka Bobby Z.)
  86.  
  87.   Letters both in Russian and in English are welcome. Please do not use any
  88.   other language if you want to be answered. Letter bombs are always
  89.   returned to sender... shhhh-boom-BANG! :)
  90.  
  91.   Thank you for your interest in B-coolWare products.
  92.  
  93.  ------------------------------------------------------------------------------
  94.  
  95.  Description.
  96.  ~~~~~~~~~~~~
  97.  This Borland Pascal unit was developed to give you the opportunity to improve
  98.  user interface of your DOS text mode applications written in Pascal by adding
  99.  "graphical" screen controls to your applications. The only implemented control
  100.  is "graphical" mouse pointer, but routines provided in this unit can also be
  101.  used to reprogram appearance of any characters. The unit supports both real
  102.  and protected modes and can be used with almost all TUI packages available for
  103.  Pascal programmers, which include Turbo Professional and Object Professional
  104.  by TurboPower Software, Turbo Vision 1.0 and 2.0 by Borland Intl. (with some
  105.  limitations described below) as well as other commercial or handmade tools.
  106.  
  107.  Actually this unit is a port from assembly language version 1.42 of g_Mouse
  108.  with simplified initialization. Version 1.42 did not support protected mode
  109.  because Borland's extender does not handle mouse function 14h (exchange
  110.  handlers) properly (this function was used to chain any existing handlers
  111.  to g_Mouse's one). Version 1.50.7 is compatible with RTM and uses only calls
  112.  proved to work correctly under it. And it is much easier to use.
  113.  
  114.  
  115.  Programmer's notes:
  116.  ~~~~~~~~~~~~~~~~~~~
  117.  
  118.   1. This code intercepts mouse services interrupt (33h) thus making
  119.      its use extremely easy: you just need to insert reference to g_Mouse in
  120.      "uses" clause of your application. Deinitialization of system is
  121.      performed automatically thru Pascal's ExitProc mechanism. All standard
  122.      mouse functions still work o.k. with this code with some exceptions in
  123.      protected mode which are due to RTM's limited support for those functions.
  124.  
  125.   2. If you wish to use this code within your Turbo Vision applications,
  126.      you'll have to change View.WriteView's logic in part determining if mouse
  127.      pointer is within area to be redrawn. Because now mouse pointer
  128.      occupies 4 characters instead of 1 it may happen that WriteView deter-
  129.      mine that mouse pointer is outside the area and do not hide it while
  130.      it actually should.
  131.      Also note that you should call DoneGMouse explicitly AFTER any call to
  132.      DoneEvents and resume g_Mouse operation by calling InitGMouse BEFORE
  133.      call to InitEvents. On program startup/exit it is done automatically but
  134.      when you do something weird like executing another process you should
  135.      shut down TV's managers first and then shut down g_Mouse. This makes
  136.      TV 2.0's TApplication.DOSShell unusable. You should always override it if
  137.      you intend to exec child processes from within your TV application using
  138.      TApplication.DOSShell method (see example program TUTOR01.PAS).
  139.   3. One conditional define affects the way code is compiled:
  140.  
  141.      TrackVideoMode
  142.  
  143.      If this is defined then mouse interrupt handler instantly calls INT 10h
  144.      function 0Fh (get current video mode) and suspends if current video mode
  145.      is other than 03h (80x25 color). Operation become a bit slower but you
  146.      won't get any probs when switching to other modes (80x50 for example).
  147.      You'll have to add other modes you want to support by yourself (like
  148.      SuperVGA 130xXX modes with 8x14 and 8x16 characters).
  149.  
  150.  
  151.  History:
  152.  ~~~~~~~~
  153.  
  154.    26 Oct 1994   ported and adapted assembly language version 1.42 to Pascal.
  155.          adapted for protected mode operation.
  156.  
  157. }
  158.  
  159. {$X+,G+,S-,P-,R-}
  160. {$C PRELOAD FIXED PERMANENT}
  161.  
  162. unit g_Mouse;
  163.  
  164. interface
  165.  
  166. type
  167.     CharMatrix = array[0..31] of Byte;
  168.  
  169. procedure InitGMouse( FlipMode : Boolean );
  170. { initialize g_Mouse system. FlipMode affects the movement of pointer. If
  171.   it is True, the pointer will move smooth, but characters will appear to
  172.   be somehow "wider" then usually. }
  173.  
  174. procedure DoneGMouse;
  175. { deinitialize g_Mouse system. Called automatically on program end, but you
  176.   will need to do it manually when executing child processes or something like
  177.   that. }
  178.  
  179. procedure SetMouseChars(C1Code, C2Code, C3Code, C4Code : Byte);
  180. { change characters used for mouse pointer. Note that these characters' maps
  181.   will be corrupted at runtime reflecting mouse movement. You should hide
  182.   mouse pointer before invoking this procedure. }
  183.  
  184. procedure SetPointerShape( var AND_Mask, OR_Mask );
  185. { used to change mouse pointer shape. AND_Mask and OR_Mask should be arrays of
  186.   at least CharSize bytes. }
  187.  
  188. procedure GetPointerShape( var AND_Mask, OR_Mask );
  189. { fills AND_Mask and OR_Mask arrays with current -and- and -or- masks that
  190.   represents mouse pointer. }
  191.  
  192. procedure GetCharMatrix( C : Word; var Matrix : CharMatrix);
  193. { returns bitmap for character C. If requested character is one of those used
  194.   to represent mouse pointer the Matrix will be filled with zeros. }
  195.  
  196. procedure SetCharMatrix( C : Word; var Matrix : CharMatrix);
  197. { sets character C's bitmap to Matrix. Unused scanlines should be zeroed. 
  198.   Does not change characters currently used to represent mouse pointer. }
  199.  
  200. const
  201.     Active   : Boolean = False;    { gMouse system is active }
  202.     CharSize : Word = 16;        { character height in scanlines }
  203.  
  204. implementation
  205.  
  206. uses Dos;
  207.  
  208. const
  209.     CurX     : Word = 0;        { current X position }
  210.     CurY     : Word = 0;        { current Y position }
  211.     C1Char   : Word = $DE;        { character to use as #1 }
  212.     C2Char   : Word = $DD;        { --"-- #2 }
  213.     C3Char   : Word = $D7;        { --"-- #3 }
  214.     C4Char   : Word = $D8;        { __"__ #4 }
  215.     C1       : array[1..16] of Byte = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
  216.     C2       : array[1..16] of Byte = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
  217.     C3       : array[1..16] of Byte = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
  218.     C4       : array[1..16] of Byte = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
  219.     Visible  : Boolean = False;    { mouse pointer is visible }
  220.     ModeFlip : Boolean = False;    { using 8 pixel-wide chars }
  221.         SaveBuf  : array[1..32] of Word = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  222.                                            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
  223.     OldChars : array[1..4] of Byte = (0,0,0,0);
  224.     OldPos   : Word = 0;
  225.     OldEvents: Word = 0;        { holds old event mask }
  226.  
  227.     OldHandler : Pointer = nil;    { holds address of old mouse handler }
  228.         i33Handler : Pointer = nil;    { holds address of INT 33 handler }
  229.         YSize    : Word = 394;        { Window max Y }
  230.         YMax     : Word = 394;        { Y max }
  231.         XSize    : Word = 638;        { Window max X }
  232.         XMin     : Word = 0;        { Window min X }
  233.         YMin     : Word = 0;        { Window min Y }
  234.  
  235.         ORMask   : array[1..16] of Byte =
  236.                    ($00,$40,$60,$70,$78,$7C,$7E,$7F,$7C,$4C,$0E,$06,$06,$00,$00,$00);
  237.  
  238.         ANDMask  : array[1..16] of Byte =
  239.                    ($3F,$1F,$0F,$07,$03,$01,$00,$00,$00,$01,$21,$F0,$F0,$F0,$FF,$FF);
  240.  
  241.  
  242. procedure Mode8BPC; near; assembler;
  243. { set 8 pixel-wide characters mode on VGA systems }
  244. asm
  245.     cli
  246.     mov    dx,3C4h
  247.     mov    al,1
  248.     out    dx,al
  249.     inc    dx
  250.     in    al,dx
  251.     or    al,1
  252.  
  253.     out    dx,al
  254.     mov    dx,3CCh
  255.     in    al,dx
  256.     and    al,0F3h
  257.  
  258.     mov    dx,3C2h
  259.     out    dx,al
  260.     mov    dx,3DAh
  261.     in    al,dx
  262.     mov    dx,3C0h
  263.     mov    al,13h
  264.     out    dx,al
  265.     sub    al,al
  266.     out    dx,al
  267.     mov    al,20h
  268.     out    dx,al
  269.     sti
  270.     mov    byte ptr C1Char,1
  271.     mov    byte ptr C2Char,2
  272.     mov    byte ptr C3Char,13
  273.     mov    byte ptr C4Char,10
  274. end;
  275.  
  276. procedure Mode9BPC; near; assembler;
  277. { set 9 pixel-wide character mode on VGA systems }
  278. asm
  279.     cli
  280.     mov    dx,3C4h
  281.     mov    al,1
  282.     out    dx,al
  283.     inc    dx
  284.     in    al,dx
  285.     and    al,0FEh
  286.     out    dx,al
  287.     mov    dx,3CCh
  288.     in    al,dx
  289.     and    al,0F3h
  290.     or    al,4
  291.     mov    dx,3C2h
  292.     out    dx,al
  293.     mov    dx,3DAh
  294.     in    al,dx
  295.     mov    dx,3C0h
  296.     mov    al,13h
  297.     out    dx,al
  298.     sub    al,al
  299.     dec    al
  300.     out    dx,al
  301.     mov    al,20h
  302.     out    dx,al
  303.     sti
  304. end;
  305.  
  306. procedure GetNewPos; near; forward;
  307. procedure gShowMouse; near; forward;
  308. procedure gHideMouse; near; forward;
  309.  
  310.  
  311. procedure MouseHandler; far; assembler;
  312. asm
  313.     push    seg @data
  314.     pop    ds
  315.     test    ax,1
  316.     jz    @@oldh
  317.     pusha
  318.     mov    al,Visible
  319.     push    ax
  320.     call    gHideMouse
  321.     call    GetNewPos
  322.     pop    ax
  323.     or    al,al
  324.     jz    @@2
  325.     call    gShowMouse
  326. @@2:
  327.     popa
  328. @@oldh:
  329.     push    ax
  330.     mov    ax,CurY
  331.     cwd
  332.     div    CharSize
  333.     shl    ax,3
  334.     mov    dx,ax
  335.     mov    cx,CurX
  336.     and    cl,0F8h
  337.     and    dl,0F8h
  338.     pop    ax
  339.     and    ax,OldEvents
  340.     jz    @@Q
  341.     push    si
  342.     mov    si, word ptr OldHandler
  343.     or    si, word ptr OldHandler[2]
  344.     pop    si
  345.     jz    @@Q
  346.     call    dword ptr ds:[OldHandler]
  347.     jmp    @@Q
  348.     db    13,10
  349.     db    'g_Mouse Interface  Version 1.50.7  Copyright(c) 1993,94 by B-coolWare.'
  350.     db    13,10
  351. @@Q:
  352. end;
  353.  
  354. procedure SetupRWMode; near; assembler;
  355. { set up character generator character map read/write mode }
  356. asm
  357.         push    ax
  358.         push    dx
  359.         mov     dx,3C4h
  360.         mov     ax,0402h
  361.         out     dx,ax
  362.         mov     ax,0704h
  363.         out     dx,ax
  364.         mov     dl,0CEh
  365.         mov     ax,0005h
  366.         out     dx,ax
  367.         mov     ax,0406h
  368.         out     dx,ax
  369.         mov     ax,0204h
  370.         out     dx,ax
  371.         pop     dx
  372.         pop     ax
  373. end;
  374.  
  375. procedure CloseRWMode; near; assembler;
  376. { reset video memory to normal text mode operation }
  377. asm
  378.         push    ax
  379.         push    dx
  380.         mov     dx,3C4h
  381.         mov     ax,0302h
  382.         out     dx,ax
  383.         mov     ax,0304h
  384.         out     dx,ax
  385.         mov     dl,0CEh
  386.         mov     ax,1005h
  387.         out     dx,ax
  388.         mov     ax,0E06h
  389.         out     dx,ax
  390.         mov     ax,0004h
  391.         out     dx,ax
  392.         pop     dx
  393.         pop     ax
  394. end;
  395.  
  396. procedure MoveChar; near; assembler;
  397. { copy cx words to/from video memory }
  398. asm
  399.         call    SetupRWMode
  400.         rep     movsw
  401.         call    CloseRWMode
  402. end;
  403.  
  404. procedure LoadChar; near; assembler;
  405. { read character map from video memory }
  406. asm
  407.         push    cx
  408.         shl     si,5
  409.         call    MoveChar
  410.         pop     cx
  411. end;
  412.  
  413. procedure SaveChar; near; assembler;
  414. { write character map to video memory }
  415. asm
  416.         push    cx
  417.         shl     di,5
  418.         call    MoveChar
  419.         pop     cx
  420. end;
  421.  
  422. procedure LoadChars( Ch1, Ch2, Ch3, Ch4 : Word ); near; assembler;
  423. { read our four character maps from video memory }
  424. asm
  425.     push    ds
  426.  
  427.         push    ds
  428.         pop     es
  429.  
  430.         mov     cx,CharSize
  431.         shr     cx,1
  432.         push    SegA000
  433.         pop     ds
  434.  
  435.     cld
  436.  
  437.         mov     di,offset C1
  438.         mov     si,Ch1
  439.         call    LoadChar
  440.  
  441.         mov     di,offset C2
  442.         mov     si,Ch2
  443.         call    LoadChar
  444.  
  445.         mov     di,offset C3
  446.         mov     si,Ch3
  447.         call    LoadChar
  448.  
  449.         mov     di,offset C4
  450.         mov     si,Ch4
  451.         call    LoadChar
  452.  
  453.     pop    ds
  454. end;
  455.  
  456. procedure SaveChars( Ch1, Ch2, Ch3, Ch4 : Word ); near; assembler;
  457. { store our character maps in video memory }
  458. asm
  459.         push    ds
  460.  
  461.         mov     cx,CharSize
  462.         shr     cx,1
  463.         push    SegA000
  464.         pop     es
  465.     
  466.     cld
  467.  
  468.         mov     si,offset C1
  469.         mov     di,Ch1
  470.         call    SaveChar
  471.  
  472.         mov     si,offset C2
  473.         mov     di,Ch2
  474.         call    SaveChar
  475.  
  476.         mov     si,offset C3
  477.         mov     di,Ch3
  478.         call    SaveChar
  479.  
  480.         mov     si,offset C4
  481.         mov     di,Ch4
  482.         call    SaveChar
  483.  
  484.         pop     ds
  485. end;
  486.  
  487. procedure computeOffset; near; assembler;
  488. { computes offset of character at (CurX,CurY) in video buffer }
  489. asm
  490.     push    ax
  491.         push    bx
  492.         push    dx
  493.     mov    si,CurX
  494.     shr    si,2
  495.     mov    ax,CurY
  496.     cwd
  497.     mov    bx,CharSize
  498.     div    bx
  499.     mov    bl,160
  500.     mul    bl
  501.     add    si,ax
  502.     and    si,0FFFEh
  503.     pop    dx
  504.         pop     bx
  505.         pop     ax
  506. end;
  507.  
  508. procedure UpdateChars; near; assembler;
  509. { applies -and- and -or- masks on characters behind cursor to make it visible }
  510. asm
  511.     call    computeOffset
  512.     push    SegB800
  513.     pop    es
  514.     sub    ah,ah
  515.     mov    al,es:[si]
  516.     push    ax
  517.     mov    al,es:[si+2]
  518.     push    ax
  519.     mov    al,es:[si+160]
  520.     push    ax
  521.     mov    al,es:[si+162]
  522.     push    ax
  523.     call    LoadChars
  524.     mov    cx,CurX
  525.     mov    bx,CurY
  526.     and    cx,7
  527.     mov    ax,CharSize
  528.     dec    ax
  529.     and    bx,ax
  530.     sub    si,si
  531. @@1:
  532.     cmp    bx,CharSize
  533.     jz    @@2
  534.     mov    ah, byte ptr C1[bx]
  535.     mov    al, byte ptr C2[bx]
  536.     mov    dh, byte ptr ANDMask[si]
  537.     mov    dl,0FFh
  538.     ror    dx,cl
  539.     and    ax,dx
  540.     mov    dh, byte ptr ORMask[si]
  541.     sub    dl,dl
  542.     shr    dx,cl
  543.     or    ax,dx
  544.     mov    byte ptr C1[bx],ah
  545.     mov    byte ptr C2[bx],al
  546.     inc    bx
  547.     inc    si
  548.     cmp    si,CharSize
  549.     jb    @@1
  550.     jmp    @@3
  551. @@2:
  552.     sub    bx,bx
  553. @@4:
  554.     mov    ah,byte ptr C3[bx]
  555.     mov    al,byte ptr C4[bx]
  556.     mov    dh,byte ptr ANDMask[si]
  557.     mov    dl,0FFh
  558.     ror    dx,cl
  559.     and    ax,dx
  560.     mov    dh,byte ptr ORMask[si]
  561.     sub    dl,dl
  562.     shr    dx,cl
  563.     or    ax,dx
  564.     mov    byte ptr C3[bx],ah
  565.     mov    byte ptr C4[bx],al
  566.     inc    bx
  567.     inc    si
  568.     cmp    si,CharSize
  569.     jb    @@4
  570. @@3:
  571.     push    C1Char
  572.     push    C2Char
  573.     push    C3Char
  574.     push    C4Char
  575.     call    SaveChars
  576. end;
  577.  
  578. procedure GetNewPos; assembler;
  579. { get new pointer position in mickeys (we using them instead of pixels) }
  580. asm
  581.     mov    ax,0Bh
  582.     int    33h
  583.     add    CurX,cx
  584.     add    CurY,dx
  585.     mov    ax,CurX
  586.         or      ax,ax
  587.         js      @@6
  588.     cmp    ax,XMin
  589.     jnb    @@1
  590. @@6:
  591.     mov    ax,XMin
  592.     jmp    @@2
  593. @@1:
  594.     cmp    ax,XSize
  595.     jbe    @@2
  596.     mov    ax,XSize
  597. @@2:
  598.     mov    CurX,ax
  599.     mov    ax,CurY
  600.         or      ax,ax
  601.         js      @@5
  602.     cmp    ax,YMin
  603.     jnb    @@3
  604. @@5:
  605.     mov    ax,YMin
  606.     jmp    @@4
  607. @@3:
  608.     cmp    ax,YSize
  609.     jbe    @@4
  610.     mov    ax,YSize
  611. @@4:
  612.     mov    CurY,ax
  613. end;
  614.  
  615. procedure gShowMouse; assembler;
  616. { show mouse pointer }
  617. asm
  618.     cmp    Active,0
  619.     jz    @@Q
  620.     cmp    Visible,1
  621.     jz    @@Q
  622.     push    ax
  623.         push    si
  624.         push    es
  625.     call    computeOffset
  626.     mov    OldPos,si
  627.     push    SegB800
  628.     pop    es
  629.     mov    al,es:[si]
  630.     mov    byte ptr OldChars,al
  631.     mov    al,es:[si+2]
  632.     mov    byte ptr OldChars[1],al
  633.     mov    al,es:[si+160]
  634.     mov    byte ptr OldChars[2],al
  635.     mov    al,es:[si+162]
  636.     mov    byte ptr OldChars[3],al
  637.     push    es
  638.         push    si
  639.     call    UpdateChars
  640.     pop    si
  641.         pop     es
  642.     mov    al,byte ptr C1Char
  643.     mov    ah,byte ptr C3Char
  644.     mov    es:[si],al
  645.     mov    es:[si+160],ah
  646.     cmp    CurX,632
  647.     jae    @@10        { oops! wrapping may occur }
  648.     mov    al,byte ptr C2Char
  649.     mov    ah,byte ptr C4Char
  650.     mov    es:[si+2],al
  651.     mov    es:[si+162],ah
  652. @@10:
  653.     pop    es
  654.         pop     si
  655.         pop     ax
  656.     mov    Visible,1
  657. @@Q:
  658. end;
  659.  
  660. procedure gHideMouse; assembler;
  661. { hide mouse pointer }
  662. asm
  663.     cmp    Active,0
  664.     jz    @@Q
  665.     cmp    Visible,0
  666.     jz    @@Q
  667.     push    ax
  668.         push    es
  669.         push    di
  670.     mov    di,OldPos
  671.     push    SegB800
  672.     pop    es
  673.     mov    al,byte ptr OldChars
  674.     mov    es:[di],al
  675.     mov    al,byte ptr OldChars[1]
  676.     mov    es:[di+2],al
  677.     mov    al,byte ptr OldChars[2]
  678.     mov    es:[di+160],al
  679.     mov    al,byte ptr OldChars[3]
  680.     mov    es:[di+162],al
  681.     pop    di
  682.         pop     es
  683.         pop     ax
  684.     mov    Visible,0
  685. @@Q:
  686. end;
  687.  
  688. function isVGAble : Boolean; near; assembler;
  689. { check whether current video adapter a VGA/EGA }
  690. asm
  691.     mov    ax,1A00h
  692.     int    10h
  693.     cmp    al,1Ah
  694.     jz    @@Ok
  695.     push    es        { still keeping compatibility with EGA systems }
  696.     push    Seg0040        { though they're very rare now... }
  697.     pop    es
  698.     mov    al,es:[87h]
  699.     pop    es
  700.     or    al,al
  701.     jz    @@Fail        { this is even not EGA! }
  702.     mov    CharSize,14    { EGA's text display is 640x350 pixels, }
  703.     mov    YSize,344    { characters are 14 lines high }
  704.         mov     YMax,344
  705. @@Ok:
  706.     mov    ah,0Fh        { video mode is 80x25? }
  707.     int    10h
  708.     cmp    al,3
  709.     jnz    @@Fail        { no - do not initialize }
  710.     mov     al,1
  711.         jmp     @@Q
  712. @@Fail:
  713.     sub     al,al
  714. @@Q:
  715. end;
  716.  
  717. procedure MouseInt; assembler;
  718. asm
  719.         push    ds
  720.         push    seg @data
  721.         pop     ds
  722. {$IFDEF TrackVideoMode }
  723.     push    ax
  724.     mov    ah,0Fh
  725.     push    bp
  726.     push    es
  727.     int    10h
  728.     cli        { interrupts gets enabled at this point }
  729.     pop    es
  730.     pop    bp
  731.     cmp    al,3
  732.     pop    ax
  733.     jnz    @@JOld
  734. {$ENDIF}
  735.     cmp    Active,0
  736.     jz    @@JOld
  737.     cmp    ax,1    { show mouse pointer }
  738.     jz    @@1
  739.     cmp    ax,2    { hide mouse pointer }
  740.     jz    @@2
  741.     cmp    ax,3    { get current pointer coordinates (in pixels) }
  742.     jz    @@3
  743.     cmp    ax,4    { set current pointer coordinates }
  744.     jz    @@4
  745.     cmp    ax,7    { set horizontal clipping boundaries }
  746.     jz    @@7
  747.     cmp    ax,8    { set vertical clipping boundaries }
  748.     jz    @@8
  749.     cmp    ax,0Ch    { set new event handler }
  750.     jz    @@0C
  751.     cmp    ax,14h    { exchange handlers - doesn't work in PM }
  752.     jz    @@14
  753.  
  754.     { set mouse+key handler, get mouse+key handler and other functions are
  755.           not intercepted for they are used very rarely. }
  756. @@JOld:
  757.  
  758.        (* because in PM we can't write to code segment without getting code
  759.           segment alias, I do not use here more convenient way to chain to
  760.           previous interrupt handler:
  761.  
  762.       DB    0EAh    { far jump [immediate] opcode }
  763.       DD    SaveIntVector
  764.  
  765.       because it leads to some difficulties in PM. Usually in Pascal I
  766.           do it this way:
  767.  
  768.       Because there is no way in pascal to make SaveIntVector global, I
  769.       add one function to handle, which takes one parameter - dword to
  770.       write to SaveIntVector and do an explicit call to handler with
  771.       value of current interrupt vector somewhere on program startup.
  772.        *)
  773.  
  774.     pushf
  775.     call    dword ptr [i33Handler]
  776.     pop    ds
  777.     iret
  778. @@1:
  779.     call    gShowMouse
  780.     jmp     @@out
  781. @@2:
  782.     call    gHideMouse
  783.     jmp     @@out
  784. @@3:
  785.  
  786.     pushf
  787.     call    dword ptr [i33Handler] { simulating interrupt }
  788.     push    ax
  789.     mov    ax,CurY        { substituting mouse driver's coordinates with
  790.                   ours }
  791.     cwd
  792.     div    CharSize
  793.     shl    ax,3
  794.     mov    cx,CurX
  795.     mov    dx,ax
  796.     and    cl,0F8h
  797.     and    dl,0F8h
  798.     pop    ax
  799.     jmp     @@out
  800. @@4:
  801.     mov    CurX,cx
  802.     push    dx
  803.     shr    dx,3
  804.     push    ax
  805.     mov    ax,dx
  806.     mul    byte ptr CharSize
  807.     mov    CurY,ax
  808.     pop    ax
  809.     pop    dx
  810.     jmp     @@out
  811. @@7:
  812.     mov    XMin,cx
  813.     cmp    dx,638
  814.     jb    @@71
  815.     mov    dx,638
  816. @@71:
  817.     mov    XSize,dx
  818.     jmp     @@out
  819. @@8:
  820.     push    ax
  821.     mov    ax,cx
  822.     shr    ax,3
  823.     mul    byte ptr CharSize
  824.     mov    YMin,ax
  825.     mov    ax,dx
  826.     shr    ax,3
  827.     mul    byte ptr CharSize
  828.     cmp    ax,YMax
  829.     jae    @@81
  830.     push    ax
  831.     add    ax,16
  832.     cmp    ax,YMax
  833.     pop    ax
  834.     jae    @@81
  835.     mov    YSize,ax
  836. @@81:
  837.     pop    ax
  838.     jmp     @@out
  839. @@0C:
  840.     mov    word ptr OldEvents,cx        { setting new handler address }
  841.     mov    word ptr OldHandler,dx        { we'll chain to }
  842.     mov    word ptr OldHandler[2],es
  843.     jmp     @@out
  844. @@14:
  845.     push    ax
  846.     xchg    cx,OldEvents
  847.     xchg    word ptr OldHandler,dx
  848.     mov    ax,es
  849.     xchg    word ptr OldHandler[2],ax
  850.     mov    es,ax
  851.     pop    ax
  852. @@out:
  853.         pop     ds
  854.         iret
  855. end;
  856.  
  857. procedure InitGMouse;
  858. { initialize graphical mouse pointer system }
  859. label Failed;
  860.  begin
  861.   if Active then
  862.    DoneGMouse;
  863.   asm
  864.     { check if mouse driver present and is operatable }
  865.     mov    ax,3533h
  866.     int    21h
  867.     mov    ax,es
  868.     or    ax,bx
  869.     jz    Failed
  870.     sub    ax,ax
  871.     int    33h
  872.     or    ax,ax
  873.     jz    Failed
  874.   end;
  875.   if not isVGAble then
  876.  Failed:
  877.    exit;
  878.   if FlipMode then
  879.    Mode8BPC;
  880.   ModeFlip := FlipMode;
  881.   LoadChars(C1Char, C2Char, C3Char, C4Char);
  882.   Move(C1,SaveBuf,sizeof(SaveBuf));
  883.   asm
  884.     mov    ax,0Ch
  885.     push    cs
  886.     pop    es
  887.     mov    dx,offset MouseHandler
  888.     mov    cx,7Fh
  889.     int    33h
  890.   end;
  891.   GetIntVec($33,i33Handler);
  892.   SetIntVec($33,@MouseInt);
  893.   Active := True;
  894.  end;
  895.  
  896. procedure DoneGMouse;
  897. { deinitialize graphical mouse pointer system }
  898.  begin
  899.   if not Active then
  900.    exit;
  901.   SetIntVec($33,i33Handler);
  902.   gHideMouse;
  903.   Move(SaveBuf,C1,sizeof(SaveBuf));
  904.   SaveChars(C1Char, C2Char, C3Char, C4Char);
  905.   if ModeFlip then
  906.    Mode9BPC;
  907.   asm
  908.     mov    ax,0Ch
  909.     mov    cx,[OldEvents]
  910.     mov    dx,word ptr [OldHandler][2]
  911.     mov    es,dx
  912.     mov    dx,word ptr [OldHandler]
  913.     int    33h
  914.   end;
  915.   C1Char := $DE;
  916.   C2Char := $DD;
  917.   C3Char := $D7;
  918.   C4Char := $D8;
  919.   Active := False;
  920.  end;
  921.  
  922. procedure SetMouseChars;
  923.  begin
  924.   if Active then
  925.    begin
  926.     Move(SaveBuf,C1,sizeof(SaveBuf));
  927.     SaveChars(C1Char, C2Char, C3Char, C4Char);
  928.    end;
  929.   C1Char := C1Code;
  930.   C2Char := C2Code;
  931.   C3Char := C3Code;
  932.   C4Char := C4Code;
  933.   if Active then
  934.    begin
  935.     LoadChars(C1Char, C2Char, C3Char, C4Char);
  936.     Move(C1,SaveBuf,sizeof(SaveBuf));
  937.    end;
  938.  end;
  939.  
  940.  
  941. procedure GetPointerShape;
  942.  begin
  943.   Move(ANDMask, AND_Mask, CharSize);
  944.   Move(ORMask, OR_Mask, CharSize);
  945.  end;
  946.  
  947. procedure SetPointerShape;
  948.  var SVisible : Boolean;
  949.  begin
  950.   SVisible := Visible;
  951.   if Active then
  952.    gHideMouse;
  953.   Move(AND_Mask, ANDMask, CharSize);
  954.   Move(OR_Mask,ORMask, CharSize);
  955.   if Active and SVisible then
  956.    gShowMouse;
  957.  end;
  958.  
  959. procedure GetCharMatrix; assembler;
  960. asm
  961.     mov    si,C
  962.     cmp    si,C1Char
  963.     jz    @@fill0
  964.     cmp    si,C2Char
  965.     jz    @@fill0
  966.     cmp    si,C3Char
  967.     jz    @@fill0
  968.     cmp    si,C4Char
  969.     jz    @@fill0
  970.     shl    si,5
  971.     mov    cx,16
  972.     push    ds
  973.     push    SegA000
  974.     pop    ds
  975.     les    di,Matrix
  976.     cld
  977.     call    MoveChar
  978.     pop    ds
  979.     jmp    @@Q
  980. @@fill0:
  981.     cld
  982.     les    di,Matrix
  983.     sub    ax,ax
  984.     mov    cx,16
  985.     rep    stosw
  986. @@Q:
  987. end;
  988.  
  989. procedure SetCharMatrix; assembler;
  990. asm
  991.     mov    al,Visible
  992.     push    ax
  993.     cmp    Active,0
  994.     jz    @@1
  995.     call    gHideMouse
  996. @@1:
  997.     mov    di,C
  998.     cmp    di,C1Char
  999.     jz    @@skip
  1000.     cmp    di,C2Char
  1001.     jz    @@skip
  1002.     cmp    di,C3Char
  1003.     jz    @@skip
  1004.     cmp    di,C4Char
  1005.     jz    @@skip
  1006.     shl    di,5
  1007.     mov    cx,16
  1008.     push    SegA000
  1009.     pop    es
  1010.     push    ds
  1011.     lds    si,Matrix
  1012.     cld
  1013.     call    MoveChar
  1014.     pop    ds
  1015. @@skip:
  1016.     pop    ax
  1017.     or    al,al
  1018.     jz    @@Q
  1019.     cmp    Active,0
  1020.     jz    @@Q
  1021.     call    gShowMouse
  1022. @@Q:
  1023. end;
  1024.  
  1025. const
  1026.  
  1027.      OldExitProc : Pointer = nil;
  1028.  
  1029. procedure gMouseExitProc; far;
  1030.  begin
  1031.   ExitProc := OldExitProc;
  1032.   DoneGMouse;
  1033.  end;
  1034.  
  1035. begin
  1036.  OldExitProc := ExitProc;
  1037.  ExitProc := @gMouseExitProc;
  1038.  InitGMouse(True);
  1039. end.
  1040.